package com.xudu.xianrendongculturaltravelbackend.controller;

import cn.hutool.core.lang.Pair;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xudu.xianrendongculturaltravelbackend.algorithm.TagMatchAlgorithmUtil;
import com.xudu.xianrendongculturaltravelbackend.annotation.AuthCheck;
import com.xudu.xianrendongculturaltravelbackend.common.BaseResponse;
import com.xudu.xianrendongculturaltravelbackend.common.DeleteRequest;
import com.xudu.xianrendongculturaltravelbackend.common.ResultUtils;
import com.xudu.xianrendongculturaltravelbackend.exception.ErrorCode;
import com.xudu.xianrendongculturaltravelbackend.exception.ThrowUtils;
import com.xudu.xianrendongculturaltravelbackend.mapper.RouteMapper;
import com.xudu.xianrendongculturaltravelbackend.model.dto.scenic.ScenicAddRequest;
import com.xudu.xianrendongculturaltravelbackend.model.dto.scenic.ScenicQueryRequest;
import com.xudu.xianrendongculturaltravelbackend.model.dto.scenic.ScenicUpdateRequest;
import com.xudu.xianrendongculturaltravelbackend.model.entity.Route;
import com.xudu.xianrendongculturaltravelbackend.model.entity.Scenic;
import com.xudu.xianrendongculturaltravelbackend.model.entity.User;
import com.xudu.xianrendongculturaltravelbackend.model.vo.RouteVO;
import com.xudu.xianrendongculturaltravelbackend.model.vo.ScenicVO;
import com.xudu.xianrendongculturaltravelbackend.service.ScenicService;
import com.xudu.xianrendongculturaltravelbackend.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/scenic")
public class ScenicController {

    @Resource
    private ScenicService scenicService;


    @Resource
    private UserService userService;

    @Resource
    private RouteMapper routeMapper;

    /**
     * 添加标签
     * 前端以from-data提交，所以使用MultipartFile接收
     */
    @AuthCheck(mustRole = "admin")
    @PostMapping(value = "/add")
    BaseResponse<Long> addScenic(ScenicAddRequest scenicAddRequest) {
        String scenicName = scenicAddRequest.getScenicName();
        ThrowUtils.throwIf(scenicName == null, ErrorCode.PARAMS_ERROR);

        return ResultUtils.success(scenicService.addScenic(scenicAddRequest));
    }

    @GetMapping("/page/list/vo")
    BaseResponse<Page<ScenicVO>> getListScenicVO(ScenicQueryRequest scenicQueryRequest) {
        int current = scenicQueryRequest.getCurrent();
        int pageSize = scenicQueryRequest.getPageSize();
        //pageSize = 8;
        Page<Scenic> scenicPage = new Page<>(current, pageSize);

        QueryWrapper<Scenic> scenicQueryWrapper = new QueryWrapper<>();
        Long id = scenicQueryRequest.getId();
        if (id != null){
            scenicQueryWrapper.lambda().eq(Scenic::getId, id);
        }
        String scenicName = scenicQueryRequest.getScenicName();
        if (scenicName != null){
            scenicQueryWrapper.lambda().like(Scenic::getScenicName, scenicName);
        }
        String tags = scenicQueryRequest.getTags();
        if (tags != null){
            scenicQueryWrapper.lambda().like(Scenic::getTags, tags);
        }
        scenicQueryWrapper.lambda().orderByDesc(Scenic::getId);
        Page<Scenic> scenicPageResult = scenicService.page(scenicPage, scenicQueryWrapper);
        Page<ScenicVO> scenicVOPageResult = new Page<>(scenicPageResult.getCurrent(), scenicPageResult.getSize(), scenicPageResult.getTotal());
        scenicVOPageResult.setRecords(scenicPageResult.getRecords().stream().map(Scenic::objToVo).toList());
        return ResultUtils.success(scenicVOPageResult);
        // List<Scenic> scenicList = scenicService.list(scenicQueryWrapper);
        // List<ScenicVO> scenicVOList = scenicList.stream().map(Scenic::objToVo).toList();
        // return ResultUtils.success(scenicVOList);
    }

    // @GetMapping("/page/list/vo")
    // BaseResponse<Page<ScenicVO>> getListScenicVO(ScenicQueryRequest scenicQueryRequest) {
    //     QueryWrapper<Scenic> scenicQueryWrapper = new QueryWrapper<>();
    //     Long id = scenicQueryRequest.getId();
    //     if (id != null){
    //         scenicQueryWrapper.lambda().eq(Scenic::getId, id);
    //     }
    //     String scenicName = scenicQueryRequest.getScenicName();
    //     if (scenicName != null){
    //         scenicQueryWrapper.lambda().like(Scenic::getScenicName, scenicName);
    //     }
    //     String tags = scenicQueryRequest.getTags();
    //     if (tags != null){
    //         scenicQueryWrapper.lambda().like(Scenic::getTags, tags);
    //     }
    //     List<Scenic> scenicList = scenicService.list(scenicQueryWrapper);
    //     List<ScenicVO> scenicVOList = scenicList.stream().map(Scenic::objToVo).toList();
    //     return ResultUtils.success(scenicVOList);
    // }

    @AuthCheck(mustRole = "admin")
    @PostMapping("update")
    BaseResponse<Boolean> updateScenic(ScenicUpdateRequest scenicUpdateRequest) {
        Long id = scenicUpdateRequest.getId();
        ThrowUtils.throwIf(id == null || id <= 0, ErrorCode.PARAMS_ERROR);

        return ResultUtils.success(scenicService.updateScenic(scenicUpdateRequest));
    }

    @AuthCheck(mustRole = "admin")
    @PostMapping("delete")
    BaseResponse<Boolean> deleteScenic(@RequestBody DeleteRequest deleteRequest) {
        Long id = deleteRequest.getId();
        ThrowUtils.throwIf(id == null || id <= 0, ErrorCode.PARAMS_ERROR);
        List<Route> routes = routeMapper.selectList(null);
        for (Route route : routes) {
            if (route.getAlongScenics().contains(id.toString())) {
                route.setAlongScenics(route.getAlongScenics().replace(id.toString(), ""));
                routeMapper.updateById(route);
            }
        }
        boolean delete = scenicService.removeById(id);
        ThrowUtils.throwIf(!delete, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(delete);
    }

    @GetMapping("/recommend/list/vo")
    BaseResponse<List<ScenicVO>> recommendScenic(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        String userTags = loginUser.getTags();
        Gson gson = new Gson();
        List<String> userTagList = gson.fromJson(userTags, new TypeToken<List<String>>() {
        }.getType());


        QueryWrapper<Scenic> queryWrapper = new QueryWrapper<>();
        // queryWrapper.select("id", "routeTags");
        queryWrapper.isNotNull("tags");
        List<Scenic> scenicList = scenicService.list(queryWrapper);


        // 依次计算用户标签和路线标签之间的相似度
        List<Pair<Scenic, Long>> list = new ArrayList<>();
        for (Scenic scenic : scenicList) {
            String scenciTags = scenic.getTags();
            if (StringUtils.isBlank(scenciTags)) {
                continue;
            }
            List<String> routeTagsList = gson.fromJson(scenciTags, new TypeToken<List<String>>() {
            }.getType());
            long similarity = TagMatchAlgorithmUtil.minDistance(userTagList, routeTagsList);
            list.add(new Pair<>(scenic, similarity));
        }

        // 按相似度排序
        List<Pair<Scenic, Long>> topScenicPairList = list.stream()
                .sorted((a, b) -> (int) (a.getValue() - b.getValue()))
                .limit(8)
                .toList();

        // 原本的顺序列表
        // List<Route> topRouteList = topRoutePairList.stream().map(Pair::getKey).collect(Collectors.toList());
        ArrayList<Scenic> finalScenicList = new ArrayList<>();
        for (Pair<Scenic, Long> pair : topScenicPairList) {
            finalScenicList.add(pair.getKey());
        }

        List<ScenicVO> scenicVOList = finalScenicList.stream().map(Scenic::objToVo).toList();

        return ResultUtils.success(scenicVOList);

    }

}